package com.jwiki.app.rpcui.util;

import java.lang.reflect.Method;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.jwiki.app.rpcui.attribute.ConfigAttribute;
import com.jwiki.app.rpcui.attribute.MethodAttribute;
import com.jwiki.app.rpcui.config.Configurations;

public abstract class ServiceUtils {

    public static Object invokeService(String interfaceName, String methodName) throws Exception {
        return invokeService(interfaceName, methodName, null);
    }

    public static Object invokeService(String interfaceName, String methodName, MethodAttribute methodAttr)
             throws Exception {
        return invokeService(interfaceName, methodName, methodAttr, null);
    }

    public static Object invokeService(String interfaceName, String methodName, MethodAttribute methodAttr,
            ConfigAttribute configAttr) throws Exception {
        ReferenceConfig<Object> reference = null;
        Object result = null;

        try {
            reference = getReferenceConfig(interfaceName, configAttr);
            Object instance = reference.get();
            Class<?> interfaceClass = Class.forName(interfaceName);
            if (methodAttr == null) {
                Method method = interfaceClass.getMethod(methodName);
                result = method.invoke(instance);
            } else {
                Method method = interfaceClass.getMethod(methodName, methodAttr.getParameterTypes());
                result = method.invoke(instance, methodAttr.getParameters());
            }
        } finally {
            if (reference != null) {
                reference.destroy();
            }
        }

        return result;
    }

    private static ReferenceConfig<Object> getReferenceConfig(String interfaceName, ConfigAttribute configAttr) {
        ReferenceConfig<Object> reference = new ReferenceConfig<Object>();

        Properties currentProperty = Configurations.getCurrentProperty();
        String appName = currentProperty.getProperty("dubbo.name");
        String regAddress = currentProperty.getProperty("dubbo.address");
        int regTimeout = Integer.valueOf(currentProperty.getProperty("dubbo.regTimeout"));
        int refTimeout = Integer.valueOf(currentProperty.getProperty("dubbo.refTimeout"));
        int retries = Integer.valueOf(currentProperty.getProperty("dubbo.retries"));

        ApplicationConfig appConfig = new ApplicationConfig();
        appConfig.setName(appName);
        reference.setApplication(appConfig);

        RegistryConfig regConfig = new RegistryConfig();
        regConfig.setAddress(regAddress);
        regConfig.setTimeout(regTimeout);
        reference.setRegistry(regConfig);

        reference.setRetries(retries);
        reference.setInterface(interfaceName);
        reference.setTimeout(refTimeout);
        if (configAttr != null) {
            if (StringUtils.isNotBlank(configAttr.getGroup())) {
                reference.setGroup(configAttr.getGroup());
            }
            if (StringUtils.isNotBlank(configAttr.getVersion())) {
                reference.setVersion(configAttr.getVersion());
            }
            if (StringUtils.isNotBlank(configAttr.getCheck())) {
                reference.setCheck(Boolean.valueOf(configAttr.getCheck()));
            }
            if (StringUtils.isNotBlank(configAttr.getTimeout())) {
                reference.setTimeout(Integer.valueOf(configAttr.getTimeout()));
            }
            if (StringUtils.isNotBlank(configAttr.getRetries())) {
                reference.setRetries(Integer.valueOf(configAttr.getRetries()));
            }
        }

        return reference;
    }

}
